<?php

require_once 'com/tardo/util/anomey.inc.php';
require_once 'com/tardo/util/UserAgentInfos/useragentinfo.php';

/**
 * Simplyfied user class with
 * the getNick() method.
 */
class User {
	public function getNick() {
		return 'peter';
	}
}

/**
 * Current user object. This is "null" if the
 * user isn't logged in.
 */
$user = new User();
// $user = null;

$request = new Request($user);

// -----------------------------------------------------------

if($request->getUser() == null) {
	echo 'you aren\' logged in!<br/>'; // anonymous user
} else {
	echo 'welcome '.$request->getUser()->getNick() . '<br/>'; // user is logged in
}


/**
 * Simplyfied request class with
 * the important methods for tardo..
 */
class Request {

	private $userAgent;
	private $bc;
	private $browser;
	private $os;
	private $path;
	private $domain;

	/**
	 * Session id which rests the same even
	 * if the real session id changes. So it
	 * can be used to track a visit of a user.
	 */
	public function getMeeting() {
		return '2a9c3bc8035c499ffc0217206083167d47deddc9';
	}

	/**
	 * Request method.
	 */
	public function getMethod() {
		return 'GET';
	}

	/**
	 * Trail of the page which the user wants to
	 * see (inside anomey).
	 */
	public function getTrail() {
		return 'home2/home';
	}

	/**
	 * User agent string of client.
	 */
	public function getUserAgent() {
		return 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7';
	}

	public function setUserAgent($uA) {
		$this->userAgent = $uA;
	}

	/**
	 * IP or adress of client.
	 */
	public function getRemoteAdress() {
		return '195.176.146.923';
	}

	/**
	 * Browser of Client.
	 */
	public function getBrowser() {
		return $this->browser;
	}

	public function setBrowser($browser) {
		$this->browser = $browser;
	}

	/**
	 * Country of Client.
	 */
	public function getCountry() {
		return 'Switzerlandjjk';
	}

	/**
	 * Operation System of Client.
	 */
	public function getOS() {
		return $this->os;
	}

	public function setOS($os) {
		return $this->os = $os;
	}

	/**
	 * Timstmp of request
	 */

	public function getTimeStmp() {
		return time();
	}

	public function getReferer() {
		return '';
	}

	private $user;

	public function getUser() {
		return $this->user;
	}

	public function __construct($user) {
		$this->user = $user;
	}
}


//-------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------

class Tardo_Day {

	public $clicks = 0;

	public $visits = 0;

	/**
	 * name => count
	 *
	 * @var array
	 */
	public $countries = array();

	/**
	 * id => time
	 *
	 * @var array
	 */
	public $meetings = array();

	/**
	 * os_name => ( browser_name => count )
	 *
	 * @var array
	 */
	public $os = array();

	/**
	 * trail => count
	 *
	 * @var array
	 */
	public $trails = array();

	/**
	 * host => ( path => count )
	 *
	 * @var array
	 */
	public $referers = array();

}

/**
 * One of the last ten clicks.
 */
class Tardo_Click {

	public $time;

	public $trail;

	public $nick;

	public function __construct($trail, $nick, $time = null) {
		if($time === null) {
			$time = date('c');
		}
		$this->time = $time;
		$this->trail = $trail;
		$this->nick = $nick;
	}
}

class Tardo {

	/**
	 * The request.
	 *
	 * @var Request
	 */
	private $request;

	/**
	 * The filename.
	 *
	 * @var string
	 */
	private $filename;

	/**
	 * The version of tardo.
	 *
	 * @var string
	 */
	private $version = '0.1';

	/**
	 * Reference to the current day object.
	 *
	 * @var Tardo_Day
	 */
	private $today;

	/**
	 * Associated array of all days of this month
	 * with the date (Y-m-d) as key and the day object
	 * as value. (date => Tardo_Day)
	 *
	 * @var array
	 */
	public $dates = array();

	/**
	 * Associated array of the last past clicks.
	 *
	 * @var array
	 */
	public $last10clicks = array();

	public function __construct($request) {
		$this->request = $request;

		$this->filename = "com/tardo/data/tardo_".date('Ym').".xml";

		$this->load();

		// check if day is known
		$now = date('Y-m-d');
		if(array_key_exists($now, $this->dates)) {
			$this->today = $this->dates[$now];
		} else {
			// unknown day
			$this->today = new Tardo_Day();
			$this->dates[$now] = $this->today;
		}

		$uaInfos = new UserAgentInfos($this->request->getUserAgent());

		$browser = $uaInfos->getBrowser();
		$this->request->setBrowser($browser['browser']."v:".$browser['browser_version']);

		$os = $uaInfos->getOperationSystem();
		$this->request->setOS($os['operation_system'].'v:'.$os['os_version']);
	}

	/**
	 * Loads data from XML into current object.
	 */
	private function load() {
		try {
			$xml = XML::load($this->filename);
			$this->version = (string) $xml['version'];

			foreach($xml->day as $day) {
				$tardoDay = new Tardo_Day();
				$this->dates[(string) $day['date']] = $tardoDay;

				$tardoDay->clicks = (int) $day['clicks'];
				$tardoDay->visits = (int) $day['visits'];

				foreach($day->countries->country as $country) {
					$tardoDay->countries[(string) $country['name']] = (int) $country['count'];
				}

				foreach($day->meetings->meeting as $meeting) {
					$time = (string) $meeting['time'];

					// don't read old meetings
					if(strtotime($time) > time() - 60 * 60 * 5) {
						$tardoDay->meetings[(string) $meeting['id']] = $time;
					}
				}

				foreach($day->operationSystems->os as $os) {
					foreach($os->browser as $browser) {
						if(!isset($tardoDay->os[(string) $os['type']])) {
							$tardoDay->os[(string) $os['type']] = array();
						}
						$tardoDay->os[(string) $os['type']][(string) $browser['name']] = (int) $browser['count'];
					}
				}

				foreach($day->trails->trail as $trail) {
					$tardoDay->trails[(string) $trail['name']] = (int) $trail['count'];
				}

				foreach($day->referers->host as $host) {
					foreach($host->path as $path) {
						if(!isset($tardoDay->referers[(string) $host['name']])) {
							$tardoDay->referers[(string) $host['name']] = array();
						}
						$tardoDay->referers[(string) $host['name']][(string) $path['name']] = (int) $path['count'];
					}
				}
			}

			foreach($xml->last10->clicks->click as $click) {
				$this->last10clicks[] = new Tardo_Click((string) $click['trail'], (string) $click['nick'], (string) $click['time']);
			}
		} catch(FileNotFoundException $e) {
			// no data to load
		}
	}

	/**
	 * Records the click and saves the changes.
	 */
	public function perform() {
		// check if meeting is known
		if(array_key_exists($this->request->getMeeting(), $this->today->meetings)) {
			// known meeting
			$this->addClick();
		} else {
			// new meeting
			$meeting = date('c');
			$this->today->meetings[$this->request->getMeeting()] = $meeting;

			$this->addVisit();
		}

		$this->save();
	}

	/**
	 * Increases the visit counter as well as the
	 * country and the browser counter.
	 */
	private function addVisit() {
		$this->addClick();
		$this->today->visits++;

		if(!isset($this->today->countries[$this->request->getCountry()])) {
			$this->today->countries[$this->request->getCountry()] = 0;
		}
		$this->today->countries[$this->request->getCountry()]++;

		if(!isset($this->today->os[$this->request->getOS()])) {
			$this->today->os[$this->request->getOS()] = array();
		}
		if(!isset($this->today->os[$this->request->getOS()][$this->request->getBrowser()])) {
			$this->today->os[$this->request->getOS()][$this->request->getBrowser()] = 0;
		}
		$this->today->os[$this->request->getOS()][$this->request->getBrowser()]++;

		if($this->request->getReferer() != '') {
			$referer = parse_url($this->request->getReferer());
			$refererhost = $referer['host'];
			$refererpath = $referer['path'];
		} else {
			$refererhost = 'direct';
			$refererpath = 'direct';
		}

		if(!isset($this->today->domains[$refererhost])) {
			$this->today->referers[$refererhost] = array();
		}
		if(!isset($this->today->domains[$refererhost][$refererpath])) {
			$this->today->referers[$refererhost][$refererpath] = 0;
		}
		$this->today->referers[$refererhost][$refererpath]++;

	}

	/**
	 * Increases the click counter and adds the current
	 * click to the start of last ten clicks. Aswell increas the trail
	 */
	private function addClick() {
		$this->today->clicks++;

		if(!isset($this->today->trails[$this->request->getTrail()])) {
			$this->today->trails[$this->request->getTrail()] = 0;
		}
		$this->today->trails[$this->request->getTrail()]++;

		array_unshift($this->last10clicks, new Tardo_Click($this->request->getTrail(), $this->request->getUser()->getNick()));
	}

	/**
	 * Saves the current object to the XML file.
	 */
	private function save() {
		$xml = XML :: create('tardo');
		$xml->addAttribute('version', $this->version);

		foreach($this->dates as $date => $day) {
			$xmlDay = $xml->addChild('day');
			$xmlDay->addAttribute('date', $date);
			$xmlDay->addAttribute('clicks', $day->clicks);
			$xmlDay->addAttribute('visits', $day->visits);

			$xmlCountries = $xmlDay->addChild('countries');
			foreach($day->countries as $name => $count) {
				$xmlCountry = $xmlCountries->addChild('country');
				$xmlCountry->addAttribute('name', $name);
				$xmlCountry->addAttribute('count', $count);
			}

			$xmlMeetings = $xmlDay->addChild('meetings');
			foreach($day->meetings as $id => $time) {
				$xmlMeeting = $xmlMeetings->addChild('meeting');
				$xmlMeeting->addAttribute('id', $id);
				$xmlMeeting->addAttribute('time', $time);
			}

			$xmlOperationSystems = $xmlDay->addChild('operationSystems');
			foreach($day->os as $type => $browsers) {
				$xmlOs = $xmlOperationSystems->addChild('os');
				$xmlOs->addAttribute('type', $type);
				foreach($browsers as $name => $count) {
					$xmlBrowser = $xmlOs->addChild('browser');
					$xmlBrowser->addAttribute('name', $name);
					$xmlBrowser->addAttribute('count', $count);
				}
			}

			$xmlTrails = $xmlDay->addChild('trails');
			foreach($day->trails as $name => $count) {
				$xmlTrail = $xmlTrails->addChild('trail');
				$xmlTrail->addAttribute('name', $name);
				$xmlTrail->addAttribute('count', $count);
			}

			$xmlReferers = $xmlDay->addChild('referers');
			foreach($day->referers as $host => $path) {
				$xmlHost = $xmlReferers->addChild('host');
				$xmlHost->addAttribute('name', $host);
				foreach($path as $pathname => $count) {
					$xmlPath = $xmlHost->addChild('path');
					$xmlPath->addAttribute('name', $pathname);
					$xmlPath->addAttribute('count', $count);
				}
			}
		}

		$xmllast10 = $xml->addChild('last10');
		$xmllast10clicks = $xmllast10->addChild('clicks');
		for($i = 0; $i < 10 and $i < count($this->last10clicks); $i++) {
			$xmlClick = $xmllast10clicks->addChild('click');
			$xmlClick->addAttribute('time', $this->last10clicks[$i]->time);
			$xmlClick->addAttribute('trail', $this->last10clicks[$i]->trail);
			$xmlClick->addAttribute('nick', $this->last10clicks[$i]->nick);
		}
		//Not been used, because of new idea
		/*	$xmllast10referers = $xmllast10->addChild('referers');
		for($i = 0; $i < 10 and $i < count($this->last10referers); $i++) {
		$xmlReferer= $xmllast10referers->addChild('referer');
		$xmlReferer->addAttribute('time', $this->last10referers[$i]->time);
		$xmlReferer->addAttribute('domain', $this->last10referers[$i]->domain);
		}*/

		$xml->save($this->filename);
	}
}
?>
